//
//  GodController.m
//  SujetObserver
//
//  Created by Pierre DUCHENE on 25/01/10.
//  Copyright 2010 Pierre DUCHENE. All rights reserved.
//

#import "AppController.h"
#import "Sun.h"
#import "TemperatureSensor.h"
#import "SubjectProtocol.h"
#import "Canal.h"
#import "Displayer.h"
#import "AtomicSpread.h"
#import "SequentialSpread.h"
#import "VersionSpread.h"
#import "BaseSpread.h"

@implementation AppController

#pragma mark -
#pragma mark Memory Management
- (void)awakeFromNib
{
	sun = [[Sun alloc] init];
	[sun addObserver:self
		  forKeyPath:kPathForTemperature
			 options:NSKeyValueObservingOptionNew
			 context:nil];
	fastestCanal = [[Canal alloc] init];
	randomCanal = [[Canal alloc] init];
	slowestCanal = [[Canal alloc] init];
	[fastestCanal setSpeed:100];
	[randomCanal setSpeed:0];
	[slowestCanal setSpeed:10];
	
	// Each canal must be observed by his displayer
	[fastestCanal addObserver:fastestDisplayer
				   forKeyPath:@"sensorData"
					  options:NSKeyValueObservingOptionNew
					  context:nil];
	[randomCanal addObserver:randomDisplayer
				  forKeyPath:@"sensorData"
					 options:NSKeyValueObservingOptionNew
					 context:nil];
	[slowestCanal addObserver:slowestDisplayer
				   forKeyPath:@"sensorData"
					  options:NSKeyValueObservingOptionNew
					  context:nil];
	
	// Add the sensor observers
	temperatureSensor = [[TemperatureSensor alloc] init];
	[(id<SubjectProtocol>)temperatureSensor attach:fastestCanal];
	[(id<SubjectProtocol>)temperatureSensor attach:randomCanal];
	[(id<SubjectProtocol>)temperatureSensor attach:slowestCanal];
	[sun setSensor:temperatureSensor];
	
	// Default strategy
	id<SpreadProtocol> temp = [[AtomicSpread alloc] init];
	[(id)temp addObserver:self
			   forKeyPath:kPathForOperationQueue
				  options:NSKeyValueObservingOptionNew
				  context:nil];
	[temperatureSensor setSpreadStrategy:[temp autorelease]];
	[strategyLabel setStringValue:@"Atomic"];
	[self showVersion:NO];
}

#pragma mark -
#pragma mark Action Methods

- (IBAction)sunAction:(id)sender
{
	if ([sun isInProgress]) {
		[sun stop];
		[sunButton setTitle:@"Auto"];
	}
	else {
		[NSThread detachNewThreadSelector:@selector(start)
								 toTarget:sun
							   withObject:nil];
		[sunButton setTitle:@"Stop"];
	}
}

- (IBAction)strategyChangeAction:(id)sender
{
	// Remove old observing
	[(id)[temperatureSensor spreadStrategy] removeObserver:self forKeyPath:kPathForOperationQueue];
	id<SpreadProtocol> temp = nil;
	BOOL showVersion = NO;
	NSString* title = [(NSButton*)sender title];
	if ([title isEqualToString:@"Atomic"]) {
		temp = [[AtomicSpread alloc] init];
	}
	else if ([title isEqualToString:@"Sequential"]) {
		temp = [[SequentialSpread alloc] init];
	}
	else if ([title isEqualToString:@"Version"]) {
		temp = [[VersionSpread alloc] init];
		showVersion = YES;
	}
	[self showVersion:showVersion];
	[(id)temp addObserver:self
			   forKeyPath:kPathForOperationQueue
				  options:NSKeyValueObservingOptionNew
				  context:nil];
	[temperatureSensor setSpreadStrategy:[temp autorelease]];
	[strategyLabel setStringValue:title];
}

- (void)showVersion:(BOOL)boolValue
{
	[fastestDisplayer setDisplayVersion:boolValue];
	[randomDisplayer setDisplayVersion:boolValue];
	[slowestDisplayer setDisplayVersion:boolValue];
}

- (void)activeStrategies:(BOOL)boolValue
{
	[atomicButton setEnabled:boolValue];
	[sequentialButton setEnabled:boolValue];
	[versionButton setEnabled:boolValue];
}

#pragma mark -
#pragma mark Binding Methods
@synthesize sliderValue;

- (void)setSliderValue:(NSInteger)newValue
{
	NSOperation* o = [[NSInvocationOperation alloc] initWithTarget:temperatureSensor
														  selector:@selector(setSensorValue:)
															object:[NSNumber numberWithInt:newValue]];
	[o start];
	[o autorelease];
	[sliderLabel setIntValue:newValue];
}

#pragma mark -
#pragma mark Observing Methods
- (void)observeValueForKeyPath:(NSString *)keyPath
					  ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{	
	id new = [change objectForKey:NSKeyValueChangeNewKey];
	if ([keyPath isEqualToString:kPathForOperationQueue]) {
		BOOL active = [(NSArray*)new count] > 0;
		[self activeStrategies:!active];
	}
	else if ([keyPath isEqualToString:kPathForTemperature]){
		NSInteger temperature = [new intValue];
		[sunTextField setIntValue:temperature]; 
	}
}

@end
